﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Twitterizer;
using System.Security.Cryptography;

namespace Twittit.Business
{
    public class UserService
    {
           
        private Twittit.DataAccess.DatabaseEntities data;
        private static UserService instance;

        private UserService()
        {
            data = new Twittit.DataAccess.DatabaseEntities();
        }

        public static UserService getInstance()
        {
            if (instance == null)
                instance = new UserService();
            return instance;
        }

        public Twittit.DataAccess.User getUserByID(int pId)
        { 
            return data.User.Where(u => u.id == pId).First();
        }

        public Twittit.DataAccess.User getUserByUsername(String pUserName)
        {
            try
            {
                return data.User.Where(u => u.twittit.Equals(pUserName)).First();
            }
            catch (Exception e)
            { return null; }
        }

        public Boolean checkPassword(String pUserName, String pPassword)
        {
            Boolean auth = false;
            Twittit.DataAccess.User u = this.getUserByUsername(pUserName);
            
            if (u != null && u.password == pPassword)
                auth = true;

            return auth;
        }

        public Twittit.DataAccess.Twit addTwitt(int userId, String content)
        {
            Twittit.DataAccess.User u = this.getUserByID(userId);
            if (u.connectToTwitter == 1)
            {
                try
                {
                    Twitterizer.OAuthTokens tokens = new Twitterizer.OAuthTokens();
                    tokens.AccessToken = "454656335-Dg2OinAmG0uofaZ97u2jMFEX6XVDucBvzw3Z8Wmw";
                    tokens.AccessTokenSecret = "2RFJwHwzYbYsMqWok1uJcNEytTJXN1VlHXp1OMyY";
                    tokens.ConsumerKey = "dpOuMdyujZaFHc4AKyWGA";
                    tokens.ConsumerSecret = "U4a7XHoczfXiEx7gCGvKJOwiRsZeAngA890lU";

                    Twitterizer.TwitterResponse<Twitterizer.TwitterStatus> tweetResponse = Twitterizer.TwitterStatus.Update(tokens, u.twittit + " : " + content);
                }
                catch (Exception e) { }
            }
           
            return Twittit.Business.TwittService.getInstance().addTwitt(userId, content);
        }

        public List<Twittit.DataAccess.User> suggestUsers(int userId)
        {
            List<Twittit.DataAccess.User> all = data.User.ToList();

             var q = from u in data.User
                     from s in data.Subscription
                     where u.id == s.user_id
                     where s.subscriber == userId
                     select u;

             List<Twittit.DataAccess.User> l = q.ToList();
             foreach(Twittit.DataAccess.User user in l )
             {
                 all.Remove(user);
             }

             all.Remove(this.getUserByID(userId));

             all = this.Shuffle(all);

             all = all.Take(10).ToList();

             return all;
        }

        public int countSubscribers(int userId)
        {
            var q = from u in data.User
                    from s in data.Subscription
                    where u.id == s.subscriber
                    where s.user_id == userId
                    where s.confirm == 1
                    where u.id != userId
                    select u;
            return q.ToList().Count();
        }

        public List<Twittit.DataAccess.User> getSubscribers(int userId){
            var q = from u in data.User
                    from s in data.Subscription
                    where u.id == s.subscriber
                    where s.user_id == userId
                    where s.confirm == 1
                    where u.id != userId
                    select u;
            return q.ToList();
        }

        public int countPendingRequests(int userId)
        {
            var q = from u in data.User
                    from s in data.Subscription
                    where u.id == s.user_id
                    where s.user_id == userId
                    where s.confirm == 0
                    select u;
            return q.ToList().Count();
        }

        public int countSubscribed(int userId)
        {
            var q = from u in data.User
                    from s in data.Subscription
                    where u.id == s.user_id
                    where s.subscriber == userId
                    where s.confirm == 1
                    where u.id != userId
                    select u;
            return q.ToList().Count();
        }

        public List<Twittit.DataAccess.User> getSubscribed(int userId)
        {
            var q = from u in data.User
                    from s in data.Subscription
                    where u.id == s.user_id
                    where s.subscriber == userId
                    where s.confirm == 1
                    where u.id != userId
                    select u;
            return q.ToList();
        }

        public int countUserPosts(int userId)
        {
            try
            {
                var q = from t in data.Twit
                        where t.user_id == userId
                        select t;

                return q.ToList().Count();
            }
            catch (Exception e)
            { return 0; }
        }

        public List<Twittit.DataAccess.Twit> getTwitts(int userId)
        {
            try
            {
                var q = from t in data.Twit
                        from s in data.Subscription
                        where t.user_id == s.user_id
                        where s.subscriber == userId
                        where s.confirm == 1
                        orderby t.date descending
                        select t;

                return q.ToList();
            }
            catch (Exception e)
            { return null; }
        }

        public List<Twittit.DataAccess.Twit> getTaggedTwitts(int userId) {
            try
            {
                DataAccess.User usr = this.getUserByID(userId);
                var q = from twit in data.Twit
                        from tag in data.Tag
                        from ttag in data.TwittitTag
                        where twit.id == ttag.twittit_id
                        where ttag.tag_id == tag.id
                        where tag.tag1 == usr.twittit
                        orderby twit.date descending
                        select twit;

                return q.ToList();
            }
            catch (Exception e)
            { return null; }
        }

        public List<Twittit.DataAccess.Twit> getTwittsByTag(String value)
        {
            try
            {
                var q = from twit in data.Twit
                        from ttag in data.TwittitTag
                        from tag in data.Tag
                        where twit.id == ttag.twittit_id
                        where ttag.tag_id == tag.id
                        where tag.tag1 == value
                        orderby twit.date descending
                        select twit;

                return q.ToList();
            }
            catch (Exception e)
            { return null; }     
        }

        public List<Twittit.DataAccess.Twit> getUserTwitts(int userId)
        {
            try
            {
                var q = from t in data.Twit
                        where t.user_id == userId
                        orderby t.date descending
                        select t;

                return q.ToList();
            }
            catch (Exception e)
            { return null; }
        }

        public List<Twittit.DataAccess.User> getRequests(int userId)
        {
            try
            {
                var q = from u in data.User
                        from s in data.Subscription
                        where u.id == s.subscriber
                        where s.user_id == userId
                        where s.confirm == 0
                        select u;

                return q.ToList();
            }
            catch (Exception e)
            { return null; }
        }


        public int subscribe(int subscriber, int subscribeto)
        {
            Twittit.DataAccess.Subscription sub;
            try
            {
                sub = data.Subscription.Where(s => s.subscriber == subscriber).Where(s => s.user_id == subscribeto).First();
            }
            catch (Exception)
            {
                Twittit.DataAccess.User u = this.getUserByID(subscribeto);
                sub = new Twittit.DataAccess.Subscription();
                sub.subscriber = subscriber;
                sub.user_id = subscribeto;
                if (u.confirmSubscription == 0)
                    sub.confirm = 1;
                else
                    sub.confirm = 0;

                data.Subscription.AddObject(sub);
                data.SaveChanges();

                return 0;
            }

            return 1;
      
        }

        public bool hasSubscribed(int subscriber, int user)
        {
            try
            {
                Twittit.DataAccess.Subscription sub = data.Subscription.Where(s => s.subscriber == subscriber).Where(s => s.user_id == user).First();
                return true;
            }
            catch (Exception) { return false; }
            
        }

        public bool hasRequested(int subscriber, int user)
        {
            try
            {
                Twittit.DataAccess.Subscription sub = data.Subscription.Where(s => s.subscriber == subscriber).Where(s => s.user_id == user).Where(s => s.confirm == 0).First();
                return true;
            }
            catch (Exception) { return false; }

        }

        public void unSubscribe(int subscriber, int user)
        {
            try
            {
                Twittit.DataAccess.Subscription sub = data.Subscription.Where(s => s.subscriber == subscriber).Where(s => s.user_id == user).First();
                data.Subscription.DeleteObject(sub);
                data.SaveChanges();
            }
            catch (Exception) {  }
        }

        public int acceptRequest(int subscriber, int user)
        {
            Twittit.DataAccess.Subscription sub;
            try
            {
                sub = data.Subscription.Where(s => s.subscriber == subscriber).Where(s => s.user_id == user).First();
                sub.confirm = 1;
                data.SaveChanges();
                return 0;
            }
            catch (Exception)
            {
                return 1;
            }
        }

        public int denyRequest(int subscriber, int user)
        {
            Twittit.DataAccess.Subscription sub;
            try
            {
                sub = data.Subscription.Where(s => s.subscriber == subscriber).Where(s => s.user_id == user).First();
                data.Subscription.DeleteObject(sub);
                data.SaveChanges();
                return 0;
            }
            catch (Exception)
            {
                return 1;
            }
        }

        public Twittit.DataAccess.User createUser(String name, String twittit, String mail, String password)
        {
            Twittit.DataAccess.User u = new Twittit.DataAccess.User();
            u.name = name;
            u.twittit = twittit;
            u.email = mail;
            u.password = password;
            u.confirmSubscription = 0;
            u.avatar = "";
            u.aboutyou = "";
            u.inDate = DateTime.Now;
            u.localisation = "FR";
            u.connectToTwitter = 0;

            data.User.AddObject(u);
            data.SaveChanges();

            this.subscribe(u.id, u.id);
            Twittit.DataAccess.Subscription s = Twittit.Business.SubscriptionService.getInstance().confirmSubscription(u.id, u.id);

            return u;

        }

        public Twittit.DataAccess.User editUser(Twittit.DataAccess.User u, String name, String twittit, String mail, String website, String localisation, String about,byte userConfirm, bool twitter, int UserId = -1)
        {
            if (UserId > -1)
            {
                // EVIL HACK
                u = null;
                u = this.getUserByID(UserId);
            }
            u.name = name;
            u.twittit = twittit;
            u.email = mail;
            u.localisation = localisation;
            u.aboutyou = about;
            u.website = website;
            u.confirmSubscription = userConfirm;
            u.connectToTwitter = Convert.ToByte(twitter);
            data.SaveChanges();

            return u;

        }

        public bool checkTwittit(String t)
        {
             try
            {
               data.User.Where(u => u.twittit == t).First();
               return false;
            }
            catch (Exception e)
            { return true; }
        }

        public List<Twittit.DataAccess.User>  searchUser(String username)
        {
             try
            {
               return data.User.Where(u => u.twittit.StartsWith(username)).ToList();
            }
            catch (Exception e)
             { return new List<Twittit.DataAccess.User>(); }
        }

        public List<Twittit.DataAccess.User> Shuffle(List<Twittit.DataAccess.User> list)
        {
            Random rng = new Random();
            int n = list.Count;
            while (n > 1)
            {
                n--;
                int k = rng.Next(n + 1);
                Twittit.DataAccess.User value = list[k];
                list[k] = list[n];
                list[n] = value;
            }

            return list;
        }
    }
}
